/*
 *  histogram.c
 *  libCV
 *
 *  Created by Gregory Koch on 17/01/11.
 *  Copyright 2011 IFlyBotIV. All rights reserved.
 *
 */

#include "histogram.h"
#include "ccvt.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>


hist_t init_hist()
{
	hist_t hist;
	
	bzero(hist.data, sizeof(float)*SIZE_HIST);
	
	return hist;
}

hist_t calc_hist(image_t image, zone_t zone)
{
	hist_t hist;
	int x, y, pos;
	hsv_pixel_t hsv;
	
	hist = init_hist();
	
	if(!verif_zone(image, zone))
	{
		printf("libCV : zone out of image");
		exit(EXIT_FAILURE);
	}
	
	if(image.type == IMG_BGR24)
	{
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				pos = image.stride * (zone.pos.y + y)
				+ (zone.pos.x + x) * 3;
				
				hsv = ccvt_rgb24_hsv(image.data[pos+2], image.data[pos+1], image.data[pos]);
				hist.data[hsv.hue]++;
			}	
		}
	}
	else if(image.type == IMG_RGB24)
	{
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				pos = image.stride * (zone.pos.y + y)
				+ (zone.pos.x + x) * 3;
                
				hsv = ccvt_rgb24_hsv(image.data[pos], image.data[pos+1], image.data[pos+2]);
				hist.data[hsv.hue]++;
			}	
		}
	}
	else
	{
		perror("libCV : calc_hist() supports only rgb ang bgr images");
		exit(EXIT_FAILURE);
	}
    
	
	return hist;
}

hist_t calc_nhist(image_t image, zone_t zone)
{
	hist_t hist;
	int x, y, pos;
	hsv_pixel_t hsv;
	float max;
	
	hist = init_hist();
	
	if(!verif_zone(image, zone))		
	{
		printf("libCV : zone out of image");
		exit(EXIT_FAILURE);
	}
	
	if(image.type == IMG_BGR24)
	{
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{				
				pos = image.stride * (zone.pos.y + y)
				+ (zone.pos.x + x) * 3;
				
				hsv = ccvt_rgb24_hsv(image.data[pos+2], image.data[pos+1], image.data[pos]);
				hist.data[hsv.hue]++;
			}	
		}
	}
	else if(image.type == IMG_RGB24)
	{
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{				
				pos = image.stride * (zone.pos.y + y)
				+ (zone.pos.x + x) * 3;
				
				hsv = ccvt_rgb24_hsv(image.data[pos], image.data[pos+1], image.data[pos+2]);
				hist.data[hsv.hue]++;
			}	
		}
	}
	else
	{
		perror("libCV : calc_nhist() supports only rgb ang bgr images");
		exit(EXIT_FAILURE);
	}
    
	max=0;
	
	for(x=0; x<SIZE_HIST; x++)
	{
		max = max < hist.data[x] ? hist.data[x] : max;
	}
    
	for(x=0; x<SIZE_HIST; x++)
	{
		hist.data[x] /= max;
	}
	
	return hist;
}

hist_t calc_weighted_hist(image_t image, zone_t zone)
{
	hist_t hist;
	int x, y, pos;
	hsv_pixel_t hsv;
	float dist;
	
	hist = init_hist();
	
	if(!verif_zone(image, zone))
	{
		printf("libCV : zone out of image");
		exit(EXIT_FAILURE);
	}
	
	if(image.type == IMG_BGR24)
	{
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				dist = kernel_dist(zone, init_pos(x, y));
				
				pos = image.stride * (zone.pos.y + y)
				+ (zone.pos.x + x) * 3;
				
				hsv = ccvt_rgb24_hsv(image.data[pos+2], image.data[pos+1], image.data[pos]);
				hist.data[hsv.hue] += dist;
			}	
		}
	}
	else if(image.type == IMG_RGB24)
	{
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				dist = kernel_dist(zone, init_pos(x, y));
				
				pos = image.stride * (zone.pos.y + y)
				+ (zone.pos.x + x) * 3;
				
				hsv = ccvt_rgb24_hsv(image.data[pos], image.data[pos+1], image.data[pos+2]);
				hist.data[hsv.hue] += dist;
			}	
		}
	}
	else
	{
		perror("libCV : calc_weighted_hist() supports only rgb ang bgr images");
		exit(EXIT_FAILURE);
	}
	
	return hist;
}

hist_t calc_weighted_nhist(image_t image, zone_t zone)
{
	hist_t hist;
	int x, y, pos, i;
	hsv_pixel_t hsv;
	float dist;
	float max, tmp;
	
	hist = init_hist();
	
	if(!verif_zone(image, zone))
	{
		printf("libCV : zone out of image");
		exit(EXIT_FAILURE);
	}
    
	if(image.type == IMG_BGR24)
	{
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				dist = kernel_dist(zone, init_pos(x, y));
				
				pos = image.stride * (zone.pos.y + y)
				+ (zone.pos.x + x) * 3;
				
				hsv = ccvt_rgb24_hsv(image.data[pos+2], image.data[pos+1], image.data[pos]);
				hist.data[hsv.hue] += dist;
			}	
		}
	}
	else if(image.type == IMG_RGB24)
	{
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				dist = kernel_dist(zone, init_pos(x, y));
				
				pos = image.stride * (zone.pos.y + y)
				+ (zone.pos.x + x) * 3;
				
				hsv = ccvt_rgb24_hsv(image.data[pos], image.data[pos+1], image.data[pos+2]);
				hist.data[hsv.hue] += dist;
			}	
		}
	}
	else
	{
		perror("libCV : calc_weighted_nhist() supports only rgb ang bgr images");
		exit(EXIT_FAILURE);
	}
    
	max=0;
    
	for(i=0; i<SIZE_HIST; i++)
	{
		max = max < hist.data[i] ? hist.data[i] : max;
	}
    
	for(i=0; i<SIZE_HIST; i++)
	{
        tmp = (1.0/max) * hist.data[i];
        
        
		hist.data[i] = tmp > 1 ? 1 : tmp;
        
	}
	
	return hist;
}

float correl_hist(hist_t hist1, hist_t hist2)
{
	int i;
	float m1;
	float m2;
	float tmp1, tmp2, tmp3;
	
	m1 = 0;
	m2 = 0;
	
	for(i=0; i<SIZE_HIST; i++)
	{
		m1 += hist1.data[i];
		m2 += hist2.data[i];
	}
	
	m1 /= SIZE_HIST;
	m2 /= SIZE_HIST;
	
	tmp1 = 0;
	tmp2 = 0;
	tmp3 = 0;
	
	for(i=0; i<SIZE_HIST; i++)
	{
		tmp1 += (hist1.data[i] - m1) * (hist2.data[i] - m2);
		tmp2 += (hist1.data[i] - m1) * (hist1.data[i] - m1);
		tmp3 += (hist2.data[i] - m2) * (hist2.data[i] - m2);
	}
	
	return (tmp1/(float)sqrt(tmp2 * tmp3));
}

float dist_hist(hist_t hist1, hist_t hist2)
{
	float tmp;
	int i;
	
	tmp = 0;
	
	for(i=0; i<SIZE_HIST; i++)
	{
		tmp += sqrt(hist1.data[i] * hist2.data[i]);
	}
	
	return (float)pow(1.0 - tmp, 0.5);
}

